#include "ThreadTracker.h"

ThreadTracker::ThreadTracker(TorrentInfo* informacionTorrent, const string &peerId, queue<Peer>* peers, Condition* condicionPeers, const unsigned long int puerto,unsigned int tiempoDeEspera) {

	this->infoTorrent = informacionTorrent;
	this->peerId = peerId;
	this->puerto = puerto;
	this->peers = peers;
	this->condicionPeers = condicionPeers;
	this->intervaloDeComunicacion = tiempoDeEspera;
	this->trackerId = "";
	this->respuesta = NULL;
	this->event = "started";
}

ThreadTracker::~ThreadTracker() {

}

void* ThreadTracker::run() {

	bool error = false;
	string datoRecibido;


	while((!this->getStop())) {

		this->respuesta = NULL;

		error = !this->conexion.conectar(this->infoTorrent->getTrackerHostname(), this->infoTorrent->getPuerto());

		if (!error) {
			error = !this->conexion.enviar(protocolo.announceTracker(this->infoTorrent->getTrackerAnnounce(), this->urlEncoder.encodear(this->infoTorrent->getHashInfo(), false), this->peerId, this->puerto, this->getCantSubida(),this->getCantBajada(), this->getCantQueFalta(), false, this->trackerId, this->event));
			this->event = "";

			if (!error) {
				error = !this->conexion.recibir(datoRecibido);
				if (!error) {
					this->respuesta = dynamic_cast<RespuestaTracker*>(this->protocolo.procesar(datoRecibido));
				}
			}
			this->conexion.shutdownAndClose();


			if (this->respuesta != NULL) {
				/* Se actualiza el intervalo de tiempo en el que se debe comunicar con el tracker */
				if ( this->respuesta->getIntervalo() != -1) {
					this->intervaloDeComunicacion = this->respuesta->getIntervalo();
				}

				/* Si todavia no se recibio el id del tracker, se lo actualiza */
				if ( this->trackerId == "" ) {
					this->trackerId = this->respuesta->getTrackerId();
				}

				vector<Peer> vecPeers = this->respuesta->getPeers();
				vector<Peer>::iterator it = vecPeers.begin();

				this->condicionPeers->mutexLock();

				for ( ; it != vecPeers.end(); it++){
					this->peers->push(*it);
					if( this->peers->size() == 1){
						this->condicionPeers->signal();
					}
				}

				this->condicionPeers->mutexUnlock();
			}
		}

		/* Se duerme el thread el intervalo de tiempo que comunico el tracker */
		//sleep(this->intervaloDeComunicacion);
		sleep(10);
	}

	return NULL;
}

void ThreadTracker::stop() {
	//TODO hacer el stop
	return;
}


string ThreadTracker::getCantSubida() {

	string aux;
	this->mutexCantSubida.lock();
	aux = this->cantSubida;
	this->mutexCantSubida.unlock();

	return aux;
}

string ThreadTracker::getCantBajada() {

	string aux;
	this->mutexCantBajada.lock();
	aux = this->cantBajada;
	this->mutexCantBajada.unlock();

	return aux;
}

string ThreadTracker::getCantQueFalta() {

	string aux;
	this->mutexCantQueFalta.lock();
	aux = this->cantQueFalta;
	this->mutexCantQueFalta.unlock();

	return aux;
}


void ThreadTracker::setCantSubida(const string &cantSubida) {

	this->mutexCantSubida.lock();
	this->cantSubida = cantSubida;
	this->mutexCantSubida.unlock();
}

void ThreadTracker::setCantBajada(const string &cantBajada) {

	this->mutexCantBajada.lock();
	this->cantBajada = cantBajada;
	this->mutexCantBajada.unlock();
}

void ThreadTracker::setCantQueFalta(const string &cantQueFalta) {

	this->mutexCantQueFalta.lock();
	this->cantQueFalta = cantQueFalta;
	this->mutexCantQueFalta.unlock();
}
